<template>
  <div class="meeting-room">
    <input
      type="checkbox"
      id="check"
      v-model="show.control"
    />
    <label for="check">
      <i
        class="label el-icon-s-fold"
        id="btn"
      />
      <i
        class="label el-icon-s-unfold"
        id="cancel"
      />
    </label>
    <div class="sidebar">
      <header>控制面板</header>
      <div class="sidebar-main perfect-scrollbar">
        <div class="memberTotal">
          当前参会人数共{{ wsMembers.length }}人
        </div>
        <div
          v-for="member in wsMembers"
          :key="member.userId"
        >
          <member-item
            :member="member"
            :hoster="hoster"
            @host="handleHost"
          />
        </div>
      </div>
      <div
        v-if="isHoster"
        class="sidebar-footer"
      >
        <el-button
          type="primary"
          size="small"
          icon="el-icon-turn-off-microphone"
          @click="handleHost('all-mic-off')"
        >全体静音</el-button>
        <el-button
          type="primary"
          size="small"
          icon="el-icon-microphone"
          @click="handleHost('all-mic-on')"
        >解除全体静音</el-button>
        <el-button size="small">
          更多
          <i class="el-icon-arrow-right"></i>
        </el-button>
      </div>
      <div
        v-else
        class="sidebar-footer"
      >
        HiTeam视频会议系统
      </div>
    </div>
    <section>
      <div class="video-box">
        <video
          id="videoHost"
          :style="`object-fit:${tool.fit}`"
          playsinline
          autoplay
          muted
        />
      </div>
      <div
        class="video-subtitle"
        v-show="tool.zimu"
      >
        <!-- <sub-title
          :message-list="messageList"
          @add="transferSubtitle"
          ref="subtitle"
        /> -->
      </div>
      <div
        v-if="mgwType==='coturn'"
        class="control video-other"
        title="小视频窗口"
      >
        <span
          class="control-icon icon iconfont icon-video"
          @click="show.other=!show.other"
        />
      </div>
      <div
        class="control video-message"
        title="聊天窗口"
      >
        <el-badge
          :value="messageNumber"
          :hidden="isHidden"
          :max="99"
          class="badge-dot"
        >
          <span
            class="control-icon icon iconfont icon-conference"
            @click="show.message=!show.message"
          />
        </el-badge>
      </div>
      <div
        class="control video-tool"
        title="视频工具"
      >
        <span
          class="control-icon icon iconfont icon-operation"
          @click="show.tool=!show.tool"
        />
      </div>
      <transition name="el-fade-in-linear">
        <div
          class="tool-box"
          v-show="show.tool"
        >
          <i
            class="pack el-icon-arrow-right"
            @click="show.tool=!show.tool"
          ></i>
          <el-divider direction="vertical"></el-divider>
          <span
            v-if="tool.microphone"
            class="icon iconfont icon-mic_on green"
            title="关闭麦克风"
            @click="handleCloseMicrophone"
          ></span>
          <span
            v-else
            class="icon iconfont icon-mic_off"
            title="打开麦克风"
            @click="handleOpenMicrophone"
          ></span>
          <el-divider direction="vertical"></el-divider>
          <span
            v-if="tool.video"
            class="icon iconfont icon-video_on green"
            title="关闭摄像头"
            @click="handleCloseVideo"
          ></span>
          <span
            v-else
            class="icon iconfont icon-video_off"
            title="打开摄像头"
            @click="handleOpenVideo"
          ></span>
          <el-divider direction="vertical"></el-divider>
          <span
            v-if="tool.share"
            class="icon iconfont icon-share green"
            title="停止共享"
            @click="stopShare"
          ></span>
          <span
            v-else
            class="icon iconfont icon-share"
            title="开始共享"
            @click="startShare"
          ></span>
          <el-divider direction="vertical"></el-divider>
          <span
            v-if="tool.zimu"
            class="icon iconfont icon-zimu green"
            title="关闭字幕"
            @click="handleCloseZimu"
          ></span>
          <span
            v-else
            class="icon iconfont icon-zimu"
            title="打开字幕"
            @click="handleOpenZimu"
          ></span>
          <el-divider direction="vertical"></el-divider>
          <span
            v-if="tool.fit==='cover'"
            class="icon iconfont icon-dividingMode"
            title="包含模式"
            @click="tool.fit='contain'"
          ></span>
          <span
            v-else
            class="icon iconfont icon-dividingMode green"
            title="覆盖模式"
            @click="tool.fit='cover'"
          ></span>
          <el-divider direction="vertical"></el-divider>
          <span
            v-if="tool.record"
            class="icon iconfont icon-record_off red"
            title="停止录制"
            @click="stopRecord"
          ></span>
          <span
            v-else
            class="icon iconfont icon-record_on"
            title="开始录制"
            @click="startRecord"
          ></span>
          <el-divider direction="vertical"></el-divider>
          <span
            class="icon iconfont icon-add blue"
            title="邀请成员"
            @click="shareDialogVisible=true"
          ></span>
          <el-divider direction="vertical"></el-divider>
          <span
            v-if="mgwType==='freeswitch'"
            class="icon iconfont icon-layout"
            title="恢复"
            @click="recoverLayout"
          ></span>
          <el-divider
            v-if="mgwType==='freeswitch'"
            direction="vertical"
          ></el-divider>
          <span
            v-if="mgwType==='freeswitch'&&!tool.stream"
            class="icon iconfont icon-HardTerminal"
            title="直播"
            @click="startPushStream"
          ></span>
          <span
            v-if="mgwType==='freeswitch'&&tool.stream"
            class="icon iconfont icon-HardTerminal green"
            title="停止直播"
            @click="stopPushStream"
          ></span>
          <el-divider
            v-if="mgwType==='freeswitch'"
            direction="vertical"
          ></el-divider>
          <span
            class="icon iconfont icon-handUp"
            title="离开会议"
            @click="leaveConference"
          ></span>
        </div>
      </transition>
      <transition name="el-fade-in-linear">
        <div
          id="videoWindows"
          class="other-box perfect-scrollbar"
          v-show="show.other"
        >
          <video
            id="videoPlayer"
            style="width:1px;height:1px;"
            playsinline
            autoplay
            muted
          ></video>
        </div>
      </transition>
      <transition name="el-fade-in-linear">
        <div
          class="message-box"
          v-show="show.message"
        >
          <chat
            :cid="cid.toString()"
            :messages="messages"
            :founderId="founder"
            @msg="handleMessage"
          />
        </div>
      </transition>
    </section>
    <!-- <form-dialog
      title="麦克风测试"
      :visible.sync="soundSetDialogVisible"
      width="500px"
      @close="handleVoiceRegisterCancel"
    >
      <sound-set-form
        @submit="handleVoiceRegisterSubmit"
        @cancel="handleVoiceRegisterCancel"
      />
    </form-dialog>
    <form-dialog
      title="分享会议"
      :visible.sync="shareDialogVisible"
      width="500px"
    >
      <share-form
        :meetingInfo="meetingInfo.conferenceBase"
        @submit="shareDialogVisible=false"
        @cancel="shareDialogVisible=false"
      />
    </form-dialog> -->
  </div>
</template>

<script>
import XChatKit from 'XChatKit'
import { mapGetters, mapActions } from 'vuex'
import { mgw4http } from '@/api/mgw.js'
import MemberItem from './MemberItem'
// import ShareForm from './form/ShareForm'
// import SubTitle from './SubTitle'
import chat from './chat'
import { dateFormat } from '@/utils/time'
import { handleParamInUrl } from '@/utils/url'
import CommonWebSocket from '@/utils/websocket'
import { conferenceWebSocketUrl } from '@/api/websocket'
import {
  judgeBlackList,
  conferencesInfo,
  storeNetworkData
} from '@/api/conferences'
export default {
  name: 'MeetingRoom',
  components: {
    MemberItem,
    // ShareForm,
    chat
    // SubTitle
  },
  data () {
    return {
      cid: '',
      mgwType: '', // freeswitch
      videoPlayer: null,
      videoWindows: null,
      videoHost: null,
      myjson: null,
      xchatkit: null,
      // 各个面板显隐控制
      show: {
        control: true,
        message: false,
        tool: true,
        other: false
      },
      // 声纹
      soundSetDialogVisible: false,
      // 分享
      shareDialogVisible: false,
      meetingInfo: {
        conferenceBase: {},
        members: []
      },
      // 本地方流缓存
      shareTemp: null,
      // websocket
      ws: null,
      // 会议成员
      wsMembers: [],
      // 创建者
      founder: '',
      // 当前主流
      currentStreamId: null,
      // 工具栏状态
      tool: {
        microphone: true,
        video: true,
        share: false,
        zimu: false,
        fit: 'contain',
        record: false,
        stream: false
      },
      // 起始索引
      startStreamIndex: 0,
      // 页面大小
      pageSize: 3,
      // 消息
      messages: [
        {
          userName: '系统消息',
          userMessage: '您已进入会议室'
        }
      ],
      // 消息数量
      messageNumber: 0,
      performanceInfo: {
        sendInfo: {
          // 总丢包数
          packetsLost: 0,
          // 每秒丢包数
          packetsLostPerSecond: 0,
          // 发送包数
          packetsSent: 0,
          // 每秒发送包数
          packetsSentPerSecond: 0,
          // 发送比特数
          bytesSent: 0,
          // 每秒发送比特数
          bytesSentPerSecond: 0,
          // 累计编码视频帧数
          framesEncoded: 0,
          // 每秒编码视频帧数
          framesEncodedPerSecond: 0,
          // 发送端平均编码时间
          googAvgEncodeMs: 0,
          // 往返时延
          googRtt: 0,
          // 抖动
          vibrate: 0
        },
        recvInfo: {
          // 总丢包数
          packetsLost: 0,
          // 每秒丢包数
          packetsLostPerSecond: 0,
          // 接收包数
          packetsReceived: 0,
          // 每秒接收包数
          packetsReceivedPerSecond: 0,
          // 接收比特数
          bytesReceived: 0,
          // 每秒接收比特数
          bytesReceivedPerSecond: 0,
          // 累计编码视频帧数
          framesDecoded: 0,
          // 每秒编码视频帧数
          framesDecodedPerSecond: 0
        }
      },
      timer: null,
      networkDataTimer: null,
      networkDataCache: [],
      networkDataList: [],
      messageList: []
    }
  },
  computed: {
    // 主持人
    hoster () {
      const hosts = this.wsMembers.filter((item) => item.isHost)
      return hosts.length > 0 ? hosts[0].userId + '' : ''
    },
    // 是否是主持人
    isHoster () {
      return this.userId + '' === this.hoster + ''
    },
    // 是否隐藏标记
    isHidden () {
      return this.messageNumber === 0
    },
    ...mapGetters({
      hasVoice: 'hasVoice',
      userId: 'userId'
    })
  },
  watch: {
    'show.message': {
      immediate: true,
      handler (newVal) {
        newVal && (this.messageNumber = 0)
      }
    }
  },
  created () {
    this.cid = this.$route.query.conferenceId
  },
  mounted () {
    if (this.hasVoice) {
      this.handleJudgeBlackList()
    } else {
      this.soundSetDialogVisible = true
    }
  },
  updated () {
    const messageBox = document.getElementById('MessageBox')
    messageBox.scrollTop = messageBox.scrollHeight
  },
  methods: {
    ...mapActions({
      getVoice: 'user/getVoice'
    }),
    getStatsItem (peer, callback) {
      if (navigator.mozGetUserMedia) {
        peer.getStats((res) => {
          var items = []
          res.forEach((result) => {
            items.push(result)
          })
          callback(items)
        }, callback)
      } else {
        peer.getStats((res) => {
          var items = []
          res.result().forEach((result) => {
            var item = {}
            result.names().forEach((name) => {
              item[name] = result.stat(name)
            })
            item.id = result.id
            item.type = result.type
            item.timestamp = result.timestamp
            items.push(item)
          })
          callback(items)
        })
      }
    },
    // 获取网络状态
    getStats (peer) {
      this.getStatsItem(peer, (results) => {
        for (let i = 0; i < results.length; i++) {
          const res = results[i]
          // 视频信息
          if (res.mediaType === 'video') {
            console.log(res)
            // 发送数据信息
            if (res.id.indexOf('send') !== -1) {
              // 丢包数
              this.performanceInfo.sendInfo.packetsLostPerSecond =
                res.packetsLost - this.performanceInfo.sendInfo.packetsLost
              this.performanceInfo.sendInfo.packetsLost = res.packetsLost

              // 发送包数
              this.performanceInfo.sendInfo.packetsSentPerSecond =
                res.packetsSent - this.performanceInfo.sendInfo.packetsSent
              this.performanceInfo.sendInfo.packetsSent = res.packetsSent

              // 发送比特数
              this.performanceInfo.sendInfo.bytesSentPerSecond =
                res.bytesSent - this.performanceInfo.sendInfo.bytesSent
              this.performanceInfo.sendInfo.bytesSent = res.bytesSent

              // 发送帧数
              this.performanceInfo.sendInfo.framesEncodedPerSecond =
                res.framesEncoded - this.performanceInfo.sendInfo.framesEncoded
              this.performanceInfo.sendInfo.framesEncoded = res.framesEncoded

              // 平均编码时间
              this.performanceInfo.sendInfo.googAvgEncodeMs =
                res.googAvgEncodeMs

              // 网络抖动
              this.performanceInfo.sendInfo.vibrate = Math.abs(
                res.googRtt - this.performanceInfo.sendInfo.googRtt
              )
              // 往返时延
              this.performanceInfo.sendInfo.googRtt = res.googRtt
            }
            // 接收数据信息
            if (res.id.indexOf('recv') !== -1) {
              // 丢包数
              this.performanceInfo.recvInfo.packetsLostPerSecond =
                res.packetsLost - this.performanceInfo.recvInfo.packetsLost
              this.performanceInfo.recvInfo.packetsLost = res.packetsLost

              // 发送包数
              this.performanceInfo.recvInfo.packetsReceivedPerSecond =
                res.packetsReceived -
                this.performanceInfo.recvInfo.packetsReceived
              this.performanceInfo.recvInfo.packetsReceived =
                res.packetsReceived

              // 发送比特数
              this.performanceInfo.recvInfo.bytesReceivedPerSecond =
                res.bytesReceived - this.performanceInfo.recvInfo.bytesReceived
              this.performanceInfo.recvInfo.bytesReceived = res.bytesReceived

              // 发送帧数
              this.performanceInfo.recvInfo.framesDecodedPerSecond =
                res.framesDecoded - this.performanceInfo.recvInfo.framesDecoded
              this.performanceInfo.recvInfo.framesDecoded = res.framesDecoded
            }
          }
        }
      })
      // 由主持人上传会议数据
      // this.isHoster && this.handleStoreNetworkData()
    },
    // 存储网络数据发送
    async handleStoreNetworkData () {
      // 将数据加入缓存
      this.networkDataCache.push({
        cid: this.cid,
        data: JSON.stringify(this.performanceInfo),
        time: dateFormat()
      })
      // 缓存数据未到5，不上传
      if (this.networkDataCache.length < 5) {
        return
      }
      // 深拷贝一份进行上传，缓存清空
      this.networkDataList = JSON.parse(JSON.stringify(this.networkDataCache))
      this.networkDataCache = []
      // 开始上传
      await storeNetworkData(this.networkDataList)
      this.networkDataList = []
    },
    // 注册声纹
    handleVoiceRegister (file) {
      this.$request.user.voiceRegister(
        file,
        () => {
          this.handleJudgeBlackList()
        },
        (err) => {
          this.$message.error(err.msg)
        }
      )
    },
    // 提交声纹
    handleVoiceRegisterSubmit (file) {
      this.handleVoiceRegister(file)
      this.soundSetDialogVisible = false
    },
    // 取消提交声纹
    handleVoiceRegisterCancel () {
      this.soundSetDialogVisible = false
      window.close()
    },
    // 判断黑名单
    async handleJudgeBlackList () {
      const { data } = await judgeBlackList(this.cid)
      if (data) {
        this.$message.error('您暂时无权进入该会议')
      } else {
        this.init()
        this.connect()
      }
    },
    // 初始化播放器
    initVideoPlayer () {
      this.userName = window.sessionStorage.userName
      this.videoHost = document.getElementById('videoHost')
      this.videoPlayer = document.getElementById('videoPlayer')
      this.videoWindows = document.getElementById('videoWindows')
    },
    // 初始化Xchatkit
    initXchatkit () {
      this.myjson = String.url2json()
      this.myjson.fromuser = this.userId
      this.myjson.maxwidth = 9999
      this.myjson.framerate = 30
      this.myjson.callback = this.onCallback
      this.myjson.camera = 0
      this.myjson.h264 = 0
      this.myjson.recvonly = 0
      this.myjson.audiomixer = 1
      this.myjson.drawingmode = 0
    },
    // 初始化
    init () {
      this.initVideoPlayer()
      this.initXchatkit()
    },
    // 设置主流
    setVideoHost (json) {
      if ('' + this.currentStreamId === '' + json.fromuser) {
        const player = document.getElementById(
          this.currentStreamId + '_video_player'
        )
        if (player) {
          this.videoHost.srcObject = player.srcObject
        }
      }
    },
    // 添加视频
    addVideo (json) {
      const video = this.videoPlayer.cloneNode()
      video.srcObject = json.stream
      video.id = json.fromuser + '_video_player'
      video.className = 'other-box-video'
      this.videoWindows.appendChild(video)
    },
    // mgw回调
    onCallback (json) {
      console.log('onCallback (json)', json)
      if (json.msgtype === 'EventRegistered') {
        this.xchatkit.Send2WPhone(json)
      } else if (json.msgtype === 'EventJoinSucc') {
        document.title = json.fromuser
        this.xchatkit.Send2WPhone(json)
      } else if (json.msgtype === 'EventLocalStream') {
        if (!this.myjson.multiplayer) {
          return
        }

        if (!this.tool.share) {
          this.shareTemp = json.stream
        }

        // this.videoPlayer.style = 'display: none'
        const video = document.getElementById(json.fromuser + '_video_player')
        if (video) {
          video.srcObject = json.stream

          this.setVideoHost(json)
          return
        }
        this.addVideo(json)
        this.setVideoHost(json)
      } else if (
        json.msgtype === 'EventPartyAdded' &&
        json.streamtype === 'video'
      ) {
        // 获取会议数据
        let key = ''
        const pcs = this.xchatkit.GetPeers()
        console.log('获取到了pcs', pcs)
        for (const id in pcs) {
          if (id !== this.userId + '') {
            key = id
            break
          }
        }
        const pc = pcs[key]
        if (pc) {
          clearInterval(this.timer)
          this.timer = setInterval(() => {
            this.getStats(pc)
          }, 1000)
        }

        if (!this.myjson.multiplayer) {
          return
        }
        const video = document.getElementById(json.fromuser + '_video_player')

        if (video) {
          video.srcObject = json.stream

          this.setVideoHost(json)
          return
        }
        this.addVideo(json)
        this.setVideoHost(json)
      } else if (
        json.msgtype === 'EventPartyRemoved' ||
        json.msgtype === 'EventPartyDisconnected' ||
        json.msgtype === 'EventPartyClosed'
      ) {
        if (!this.myjson.multiplayer) {
          return
        }
        const video = document.getElementById(json.fromuser + '_video_player')
        if (video) {
          this.videoWindows.removeChild(video)
        }
      } else if (json.msgtype === 'EventStopSharing') {
        this.tool.share = false
        const video = document.getElementById(json.fromuser + '_video_player')
        video.srcObject = this.shareTemp

        this.setVideoHost(json)
      } else if (json.msgtype === 'EventWindowClosed') {
        while (true) {
          let found = false
          for (let i = 0; i < this.videoWindows.children.length; ++i) {
            if (
              this.videoWindows.children[i].id.endsWith('_video_player') ||
              this.videoWindows.children[i].id.endsWith('_video')
            ) {
              found = true
              this.videoWindows.removeChild(this.videoWindows.children[i])
              break
            }
          }
          if (!found) {
            break
          }
        }
        this.videoPlayer.srcObject = null
        this.videoPlayer.style = this.videoPlayer.laststyle
      }
    },
    // 加入会议
    joinConference () {
      this.xchatkit.JoinConference(this.myjson)
    },
    // 判断id是否是本人
    isMe (uid) {
      return uid + '' === this.userId + ''
    },
    // 获取会议信息
    async conferencesInfoInit () {
      const { data } = await conferencesInfo(this.cid)
      this.meetingInfo = data
      this.mgwType = this.meetingInfo.conferenceBase.mode === 1 ? 'coturn' : 'freeswitch'
      this.founder = this.meetingInfo.conferenceBase.founderId + ''
      if (this.mgwType === 'coturn') {
        this.myjson.mgw = process.env.VUE_APP_COTURN_MGW
        this.myjson.player = this.videoPlayer
        this.myjson.multiplayer = true
        this.myjson.chatroom = this.meetingInfo.conferenceBase.cid
        this.xchatkit = new XChatKit(this.myjson)
        this.joinConference()
        this.setHostVideo(this.founder)
      } else {
        const { data } = await mgw4http(this.cid)
        this.myjson.mgw = `${process.env.VUE_APP_FREESWITCH_MGW}?mgwurl=${data}`
        this.myjson.player = this.videoHost
        this.myjson.multiplayer = false
        this.myjson.chatroom = this.meetingInfo.conferenceBase.cid
        this.xchatkit = new XChatKit(this.myjson)
        this.joinConference()
      }
    },
    // 连接websocket
    connect () {
      this.ws = new CommonWebSocket({
        url: handleParamInUrl(conferenceWebSocketUrl, {
          conferenceId: this.cid,
          userId: this.userId
        }),
        openFun: () => {
          this.setUserState(true, true)
          this.getAllWsMember()
          this.conferencesInfoInit()
        },
        messageFun: (message) => {
          this.handleWebsocketMessage(message)
        }
      })
    },
    // 处理消息
    handleWebsocketMessage (message) {
      const { type } = message
      if (message.msg && type !== 6) {
        this.messages.push({
          userName: '系统消息',
          userMessage: message.msg
        })
      }
      switch (type) {
        // 获取全部会议成员信息
        case 6:
          this.wsMembers = message.data || []
          break
        // 1. 有用户加入
        // 2. 有用户离开
        // 5. 有用户改变了设备状态
        // 12. 切换主持人
        case 1:
        case 2:
        case 5:
        case 12:
          this.getAllWsMember()
          break
        // 主持人关闭某人麦克风
        case 4:
          this.isMe(message.user.userId) && this.closeMicrophone()
          this.getAllWsMember()
          break
        // 主持人打开某人麦克风
        case 7:
          this.isMe(message.user.userId) && this.openMicrophone()
          this.getAllWsMember()
          break
        // 主持人关闭某人摄像头
        case 9:
          this.isMe(message.user.userId) && this.closeVideo()
          this.getAllWsMember()
          break
        // 主持人打开某人摄像头
        case 10:
          this.isMe(message.user.userId) && this.openVideo()
          this.getAllWsMember()
          break
        // 主持人全员静音
        case 13:
          this.closeMicrophone()
          this.getAllWsMember()
          break
        // 主持人取消全员静音
        case 14:
          this.openMicrophone()
          this.getAllWsMember()
          break
        // 主持人踢人
        case 3:
          this.isMe(message.user.userId) && this.kickedOutMessage(message.msg)
          this.getAllWsMember()
          break
        // 主持人切流
        case 8:
          this.setHostVideo(message.user.userId)
          break
        // 结束会议
        case 11:
          window.close()
          break
        // 字幕消息
        case 15:
          this.handleSubtitleMessage(message.msg)
          break
        default:
          break
      }
    },
    // 生成websocket消息
    generateMessage (cmd, classification, data) {
      const msg = {
        cmd,
        classification,
        data
      }
      return JSON.stringify(msg)
    },
    // ws获取当前参会人员
    getAllWsMember () {
      const command = this.generateMessage(8, 3, {})
      this.ws.send(command)
    },
    // ws发送麦克风和摄像头状态
    setUserState (video, microphone) {
      const command = this.generateMessage(8, 4, {
        camera: video,
        voice: microphone
      })
      this.ws.send(command)
    },
    // 发送结束会议的消息
    finishConferenceMessage () {
      const command = this.generateMessage(8, 9, {})
      this.ws.send(command)
    },
    // 发送转义的字幕
    transferSubtitle (message) {
      const command = this.generateMessage(8, 13, {
        subtitle: message
      })
      this.ws.send(command)
    },
    // 设置当前客户端为主视频流
    setHostVideo (setUid) {
      if (this.mgwType === 'coturn') {
        const player = document.getElementById(setUid + '_video_player')
        if (player) {
          this.videoHost.srcObject = player.srcObject
        } else {
          this.currentStreamId = setUid
        }
      } else {
        if (this.isMe(setUid)) {
          this.xchatkit.ChangeLayout('1')
        }
      }
    },
    // 关闭麦克风
    closeMicrophone () {
      this.xchatkit.DisableMicphone(this.myjson)
      this.tool.microphone = false
    },
    // 主动关闭麦克风
    handleCloseMicrophone () {
      this.closeMicrophone()
      this.setUserState(this.tool.video, false)
    },
    // 打开麦克风
    openMicrophone () {
      this.xchatkit.EnableMicphone(this.myjson)
      this.tool.microphone = true
    },
    // 主动打开麦克风
    handleOpenMicrophone () {
      this.openMicrophone()
      this.setUserState(this.tool.video, true)
    },
    // 关闭摄像头
    closeVideo () {
      this.xchatkit.DisableCamera(this.myjson)
      this.tool.video = false
    },
    // 主动关闭摄像头
    handleCloseVideo () {
      this.closeVideo()
      this.setUserState(false, this.tool.microphone)
    },
    // 打开摄像头
    openVideo () {
      this.xchatkit.EnableCamera(this.myjson)
      this.tool.video = true
    },
    // 主动打开摄像头
    handleOpenVideo () {
      this.openVideo()
      this.setUserState(true, this.tool.microphone)
    },
    // 共享屏幕
    startShare () {
      this.tool.share = true
      this.xchatkit.StartSharing(this.myjson)
    },
    // 结束共享
    stopShare () {
      this.xchatkit.StopSharing(this.myjson)
    },
    // 开启实时字幕
    handleOpenZimu () {
      this.$message.info('实时字幕已开启')
      this.tool.zimu = true
      this.$refs.subtitle.init()
    },
    // 关闭字幕
    handleCloseZimu () {
      this.$message.info('实时字幕已关闭')
      this.tool.zimu = false
      this.$refs.subtitle.stop()
    },
    // 开始录制
    startRecord () {
      if (this.isHoster) {
        if (this.mgwType === 'coturn') {
          this.xchatkit.StartServerRecording(this.myjson)
        } else if (this.mgwType === 'freeswitch') {
          this.xchatkit.ChangeLayout('2')
        }
        this.tool.record = true
      } else {
        this.$message.warning('目前只支持主持人录制视频！')
      }
    },
    // 结束录制
    stopRecord () {
      if (this.isHoster) {
        if (this.mgwType === 'coturn') {
          this.xchatkit.StopServerRecording(this.myjson)
        } else if (this.mgwType === 'freeswitch') {
          this.xchatkit.ChangeLayout('3')
        }
        this.tool.record = false
      } else {
        this.$message.warning('目前只支持主持人录制视频！')
      }
    },
    // 恢复切流
    recoverLayout () {
      if (this.isHoster) {
        this.xchatkit.ChangeLayout('')
      }
    },
    // 开始直播
    startPushStream () {
      if (this.isHoster) {
        this.xchatkit.ChangeLayout('4')
        this.tool.stream = true
      } else {
        this.$message.warning('目前只支持主持人直播视频！')
      }
    },
    // 结束直播
    stopPushStream () {
      if (this.isHoster) {
        this.xchatkit.ChangeLayout('5')
        this.tool.stream = false
      } else {
        this.$message.warning('目前只支持主持人直播视频！')
      }
    },
    // 离开
    leaveConference () {
      if (this.isHoster) {
        this.beforeFinish()
      } else {
        window.close()
      }
    },
    // 主持人离开前的操作
    beforeFinish () {
      if (this.tool.record) {
        this.stopRecord()
      }
      this.finishConference()
    },
    // 主持人结束会议事件
    finishConference () {
      this.$request.conference.finishConference(
        this.$route.query.conferenceId,
        (res) => {
          this.xchatkit.LeaveConferenceEx(this.myjson)
          this.finishConferenceMessage()
          this.ws.close()
          this.$alert('会议已结束', '提示', {
            confirmButtonText: '确定',
            callback: (action) => {
              window.close()
            },
            showClose: false
          })
        },
        (err) => {
          this.$message.error(err.msg)
        }
      )
    },
    // 被踢出会议室消息提示框
    kickedOutMessage (kickMessage) {
      this.xchatkit.LeaveConferenceEx(this.myjson)
      this.$alert(kickMessage, '提示', {
        confirmButtonText: '确定',
        callback: (action) => {
          window.close()
        },
        showClose: false
      })
    },
    // 字幕消息处理
    handleSubtitleMessage (msg) {
      const punctuations = ['，', '。', '！', '？']
      msg && punctuations.includes(msg[0]) && (msg = msg.slice(1))
      msg && this.messageList.push(msg)
    },
    // 主持人操作事件
    handleHost (event, uid, params) {
      let command = null
      switch (event) {
        // 关闭摄像头
        case 'video-off':
          command = this.generateMessage(8, 7, { uid })
          break
        // 打开摄像头
        case 'video-on':
          command = this.generateMessage(8, 8, { uid })
          break
        // 关闭麦克风
        case 'mic-off':
          command = this.generateMessage(8, 2, { uid })
          break
        // 打开麦克风
        case 'mic-on':
          command = this.generateMessage(8, 5, { uid })
          break
        // 切流
        case 'change':
          command = this.generateMessage(8, 6, { uid })
          break
        // 切换主持人
        case 'switch':
          command = this.generateMessage(8, 10, { uid })
          break
        // 踢人
        case 'remove':
          command = this.generateMessage(8, 1, { uid })
          break
        // 修改昵称
        case 'nickname':
          command = this.generateMessage(8, 4, {
            camera: this.tool.video,
            voice: this.tool.microphone,
            nickname: params.nickname
          })
          break
        // 全体静音
        case 'all-mic-off':
          command = this.generateMessage(8, 11, {})
          break
        // 解除全体静音
        case 'all-mic-on':
          command = this.generateMessage(8, 12, {})
          break
        default:
          break
      }
      command && this.ws.send(command)
    },
    // 收到消息
    handleMessage () {
      if (!this.show.message) {
        this.messageNumber++
      }
    }
  }
}
</script>

<style lang="scss" scoped>
$bg-color: rgba(#000, 0.4);
.meeting-room {
  position: relative;
  overflow: hidden;
  .sidebar {
    position: absolute;
    height: 100%;
    background: #1f1f1e;
    color: $white;
    transition: all 0.5s ease;
    word-wrap: break-word;
    header {
      position: absolute;
      top: 0;
      width: 100%;
      text-align: center;
      background-color: #161616;
      color: white;
      user-select: none;
    }
    .sidebar-main {
      position: absolute;
      overflow-y: scroll;
      left: 0;
      right: 0;
    }
    .sidebar-footer {
      position: absolute;
      bottom: 0;
      left: 0;
      width: 100%;
      background-color: #161616;
      display: flex;
      align-items: center;
      justify-content: space-around;
    }
  }
  section {
    position: relative;
    height: 100vh;
    transition: all 0.5s;
    .video-box {
      width: 100%;
      height: 100%;
      video {
        width: 100%;
        height: 100%;
        background-color: #333;
        z-index: -1;
      }
    }
    .video-subtitle {
      position: absolute;
      bottom: 90px;
      width: 60%;
      right: 0;
      left: 0;
      margin: auto;
      height: 100px;
      text-align: center;
      /* background-color: rgba(0, 0, 0, 0.3); */
    }
    .control {
      position: absolute;
      right: 20px;
      .control-icon {
        display: block;
        border-radius: 50%;
        background-color: $bg-color;
        text-align: center;
        color: #fff;
        cursor: pointer;
      }
    }
    .tool-box {
      position: absolute;
      bottom: 20px;
      left: 50%;
      background-color: $bg-color;
      text-align: center;
      transform: translateX(-50%);
      color: $white;
      display: flex;
      align-items: center;
      box-sizing: border-box;
      .pack {
        cursor: pointer;
      }
      .icon {
        cursor: pointer;
      }
      .icon-handUp {
        color: $red;
      }
    }
    .other-box {
      background-color: $bg-color;
      position: absolute;
      top: 25px;
      right: 100px;
      overflow-y: auto;
      .other-box-video {
        width: 100% !important;
        height: 180px !important;
        object-fit: cover;
        margin-bottom: 20px;
      }
      .btn {
        width: 60%;
        background-color: rgba(#000, 0.5);
        color: $white;
        display: flex;
        justify-content: center;
        align-items: center;
        &:hover {
          cursor: pointer;
          background-color: rgba(#000, 0.3);
        }
      }
    }
    .message-box {
      background-color: $bg-color;
      position: absolute;
      bottom: 20px;
      left: 20px;
    }
  }
}

@media screen and (max-width: 6000px) and (min-width: 1601px) {
  #check:checked ~ label #btn {
    right: 350px;
  }

  #check:checked ~ label #cancel {
    right: 290px;
  }

  #check:checked ~ section {
    margin-right: 350px;
  }

  label {
    #btn {
      width: 50px;
      height: 50px;
      line-height: 50px;
      font-size: 30px;
    }
    #cancel {
      top: 15px;
      font-size: 22px;
      right: -200px;
    }
  }

  .meeting-room {
    .sidebar {
      font-size: 16px;
      right: -350px;
      width: 350px;
      header {
        font-size: 18px;
        line-height: 60px;
      }
      .sidebar-main {
        top: 60px;
        bottom: 60px;
      }
      .sidebar-footer {
        height: 60px;
      }
    }
    section {
      .tool-box {
        height: 60px;
        border-radius: 30px;
        line-height: 60px;
        font-size: 20px;
        padding: 0 20px;
        .pack {
          font-size: 20px;
          margin: 0 5px;
        }
        .icon {
          font-size: 30px;
          margin: 0 10px;
        }
      }
      .message-box {
        padding: 0 10px;
        width: 350px;
        height: 700px;
      }
      .other-box {
        width: 300px;
        height: 700px;
        .other-box-video {
          height: 180px;
        }
        .btn {
          height: 40px;
          font-size: 30px;
        }
        .top {
          border-bottom-left-radius: 30px;
          border-bottom-right-radius: 30px;
        }
        .bottom {
          border-top-left-radius: 30px;
          border-top-right-radius: 30px;
        }
      }
      .control {
        .control-icon {
          width: 60px;
          height: 60px;
          line-height: 60px;
          font-size: 30px;
        }
      }
      .video-other {
        bottom: 180px;
      }
      .video-message {
        bottom: 100px;
      }
      .video-tool {
        bottom: 20px;
      }
    }
  }
}

@media screen and (max-width: 1600px) and (min-width: 1401px) {
  #check:checked ~ label #btn {
    right: 290px;
  }

  #check:checked ~ label #cancel {
    right: 220px;
  }

  #check:checked ~ section {
    margin-right: 290px;
  }

  label {
    #btn {
      width: 50px;
      height: 50px;
      line-height: 50px;
      font-size: 25px;
    }
    #cancel {
      top: 10px;
      font-size: 20px;
      right: -200px;
    }
  }

  .meeting-room {
    .sidebar {
      font-size: 14px;
      right: -290px;
      width: 290px;
      header {
        font-size: 16px;
        line-height: 50px;
      }
      .sidebar-main {
        top: 50px;
        bottom: 50px;
      }
      .sidebar-footer {
        height: 50px;
      }
    }
    section {
      .tool-box {
        height: 50px;
        border-radius: 25px;
        line-height: 50px;
        font-size: 18px;
        padding: 0 15px;
        .pack {
          font-size: 18px;
          margin: 0 5px;
        }
        .icon {
          font-size: 25px;
          margin: 0 10px;
        }
      }
      .message-box {
        width: 280px;
        height: 500px;
      }
      .other-box {
        width: 250px;
        height: 600px;
        .other-box-video {
          height: 140px;
        }
        .btn {
          height: 35px;
          font-size: 25px;
        }
        .top {
          border-bottom-left-radius: 20px;
          border-bottom-right-radius: 20px;
        }
        .bottom {
          border-top-left-radius: 20px;
          border-top-right-radius: 20px;
        }
      }
      .control {
        .control-icon {
          width: 50px;
          height: 50px;
          line-height: 50px;
          font-size: 25px;
        }
      }
      .video-other {
        bottom: 140px;
      }
      .video-message {
        bottom: 80px;
      }
      .video-tool {
        bottom: 20px;
      }
    }
  }
}

@media screen and (max-width: 1400px) {
  #check:checked ~ label #btn {
    right: 290px;
  }

  #check:checked ~ label #cancel {
    right: 220px;
  }

  #check:checked ~ section {
    margin-right: 290px;
  }

  label {
    #btn {
      width: 50px;
      height: 50px;
      line-height: 50px;
      font-size: 25px;
    }
    #cancel {
      top: 10px;
      font-size: 20px;
      right: -200px;
    }
  }

  .meeting-room {
    .sidebar {
      font-size: 14px;
      right: -290px;
      width: 290px;
      header {
        font-size: 16px;
        line-height: 50px;
      }
      .sidebar-main {
        top: 50px;
        bottom: 50px;
      }
      .sidebar-footer {
        height: 50px;
      }
    }
    section {
      .tool-box {
        height: 50px;
        border-radius: 25px;
        line-height: 50px;
        font-size: 18px;
        padding: 0 15px;
        .pack {
          font-size: 18px;
          margin: 0 5px;
        }
        .icon {
          font-size: 25px;
          margin: 0 10px;
        }
      }
      .message-box {
        width: 280px;
        height: 500px;
      }
      .other-box {
        width: 250px;
        height: 600px;
        .other-box-video {
          height: 140px;
        }
        .btn {
          height: 35px;
          font-size: 25px;
        }
        .top {
          border-bottom-left-radius: 20px;
          border-bottom-right-radius: 20px;
        }
        .bottom {
          border-top-left-radius: 20px;
          border-top-right-radius: 20px;
        }
      }
      .control {
        .control-icon {
          width: 50px;
          height: 50px;
          line-height: 50px;
          font-size: 25px;
        }
      }
      .video-other {
        bottom: 140px;
      }
      .video-message {
        bottom: 80px;
      }
      .video-tool {
        bottom: 20px;
      }
    }
  }
}

label {
  .label {
    z-index: 1111;
    position: absolute;
    cursor: pointer;
    background-color: $bg-color;
    border-radius: 3px;
  }
  #btn {
    right: 20px;
    top: 25px;
    color: white;
    text-align: center;
    transition: all 0.5s;
  }
  #cancel {
    z-index: 1111;
    color: white;
    padding: 4px 9px;
    transition: all 0.5s;
  }
}

#check {
  display: none;
}

#check:checked ~ .sidebar {
  right: 0;
}

#check:checked ~ label #btn {
  opacity: 0;
  pointer-events: none;
}
</style>
